package com.huanf.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.huanf.domain.User;
import com.huanf.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Map;

/**
 * @author: 35238
 * 功能: 条件构造器
 * 时间: 2024-01-01 19:11
 */
@RestController
public class WrapperController {

    @Autowired
    private UserMapper userMapper;

    /*

    为了清晰表示父类子类，我们用阶梯的形式写出来，如下

    Wrapper: 条件构造抽象类，最顶端父类
        AbstractWrapper: 用于查询条件封装。该类是抽象类，有三个子类
            QueryWrapper: 封装查询的条件。除了查询还用于删除
            UpdateWrapper: 封装修改的条件，还可以封装修改的字段
            AbstractLambdaWrapper: 该类是抽象类，可以使用Lambda语法。该类是抽象类，有两个子类
                LambdaQueryWrapper: 使用Lambda语法来封装查询的条件。除了查询还用于删除
                LambdaUpdateWrapper: 使用Lambda语法来封装修改的条件

    注意: 无论是查询，删除、修改，都可使用QueryWrapper类，原因:UpdateWrapper、QueryWrapper、AbstractLambdaWrapper的父类是同一个
    注意: 下面叙述中的逻辑字段，如何判断逻辑字段对应的数据是否被删除。只需要看该逻辑字段的值即可，如果是0的话(我们创建逻辑字段时要求手动赋值为0)就表示未删除，如果是1就表示已经被逻辑删除

    */

    //--------------------------------QueryWrapper类的条件查询selectList------------------------------

    @GetMapping("/wrapper1") //浏览器访问 http://localhost:8050/wrapper1
    public String wrapper1() {
        //需求: 查询用户名包含张三，年龄在10到20之间，邮箱信息不为null的用户信息
        //由于Mapper类是最顶类，且是抽象类，所以我们需要使用Mapper类的子类，即创建'Mapper类的子类'的对象，因为是查询操作所以创建的是QueryWrapper类的对象
        QueryWrapper<User> user = new QueryWrapper<>();
        user.like("user_name","张三")//下面可以紧接着进行链式编程。注意user_name是数据库的字段
                .between("age",10,20)//ge表示大于等于，gt表示大于，le表示小于等于，lt表示小于，between表示在什么之间。注意age是数据库的字段
                .isNotNull("email");//isNotNull表示某个字段不为空。链式编程结束之后分号结尾。注意email是数据库的字段
        //上面四行的意思: 先创建指定的条件构造器queryWrapper，再使用链式编程把条件构造器赋予各种条件(也叫封装条件)。最后把赋值好的条件构造器放到下面那行
        List<User> list = userMapper.selectList(user);//返回值是list集合
        //由于要输出集合，所以我们需要使用到forEach遍历输出
        list.forEach(System.out::println);
        return "请回idea控制台查看";
    }
    //注意如果某条数据里有逻辑字段，并且逻辑字段不为空，且你在逻辑操作时删过该条数据，那么即使该条数据符合上面条件查询的条件，该条数据也不会被查询出来
    //可以理解为你之前对逻辑字段的操作虽然对数据库没有真正影响，但是对条件查询是有影响的

    //----------------------------QueryWrapper类的条件查询selectList-组装排序条件------------------------

    @GetMapping("/wrapper2") //浏览器访问 http://localhost:8050/wrapper2
    public String wrapper2() {
        //需求: 查询用户信息，按照年龄的降序排序，若年龄相同，则按照id升序排序
        //由于Mapper类是最顶类，且是抽象类，所以我们需要使用Mapper类的子类，即创建'Mapper类的子类'的对象，因为是查询操作所以创建的是QueryWrapper类的对象
        QueryWrapper<User> zidingyi_queryWrapper = new QueryWrapper<>();
        zidingyi_queryWrapper.orderByDesc("age")//asc升序(默认就是这个)，desc降序
                .orderByAsc("uid");//注意age和uid都是数据库的字段名，一定要看看你的数据库字段名是不是叫这个。同样可以用链式编程
        List<User> list = userMapper.selectList(zidingyi_queryWrapper);//返回值是list集合
        //由于要输出集合，所以我们需要使用到forEach遍历输出
        list.forEach(System.out::println);
        return "请回idea控制台查看";
    }

    //---------------------------------QueryWrapper类的条件修改 update--------------------------------

    @GetMapping("/wrapper3") //浏览器访问 http://localhost:8050/wrapper3
    public String wrapper3() {
        //需求: 将(年龄大于10并且用户名中包含有张三)或邮箱为null的用户信息修改
        QueryWrapper<User> userList = new QueryWrapper<>();
        userList.gt("age",10)//gt表示大于，也就是年龄要大于20
                .like("user_name","张三")//表示用户名中包含有a，注意链式编程中的默认连接的条件是and，所以默认就有并且的关系
                .or()//注意此时就要指定连接条件，不能使用默认的and条件，因为需求是'或'。连接条件: 链式编程的多条链，每一条链就是一个条件，这些条件的关系要么是and(默认)、or、not
                .isNull("email");//链式编程结束之后，用分号结尾
        User user = new User();
        user.setName("小明");
        user.setEmail("update@123.com");
        userMapper.update(user, userList);//返回值是受影响的行数。userList表示你要修改的数据要具备什么条件，user是修改后的数据
        return "修改成功 请到数据库查看";
    }
    //注意如果某条数据里有逻辑字段，并且逻辑字段不为空，并且该数据已经被逻辑删除了，那么此时执行这里的修改方法，该数据即使符合条件也不会被修改

    //-----------------------------------QueryWrapper类的条件的优先级----------------------------------

    @GetMapping("/wrapper4") //浏览器访问 http://localhost:8050/wrapper4
    public String wrapper4() {
        //需求: 将用户名中包含王五并且(年龄大于10或邮箱为null)的用户信息修改
        //注意: 在条件构造器中，Lambda表达式里面的条件优先执行，也就是优先级最高，且Lambda表达式内部也可以使用链式编程
        QueryWrapper<User> zidingyi_queryWrapper = new QueryWrapper<>();
        zidingyi_queryWrapper.like("user_name","王五")
                .and(i->i.gt("age",10).or().isNull("email"));//用Lambda表达式，i表示条件构造器，我们可以通过i调用方法
        //由于update方法需要一个实体类(User)的对象,然后把你想修改后的值赋值到这个对象里面
        User user = new User();
        user.setName("小红");
        user.setEmail("youxianji@123.com");
        userMapper.update(user, zidingyi_queryWrapper);//返回值是受影响的行数
        return "修改成功 请到数据库查看";
    }

    //---------------------------------组装查询语句，简单说就是怎么写查询条件-------------------------------

    @GetMapping("/wrapper5") //浏览器访问 http://localhost:8050/wrapper5
    public String wrapper5() {
        //需求: 查询用户的用户名、年龄、邮箱
        //注意: 不是查询所有字段的数据，查询的是指定字段的数据
        QueryWrapper<User> zidingyi_queryWrapper = new QueryWrapper<>();
        zidingyi_queryWrapper.select("user_name","age","email");
        //下面那行的右边获取上面那行的条件构造器对象，然后返回值是List<Map>，表示获取的数据是Map集合，最后返回的字段是List集合
        List<Map<String,Object>> mapList = userMapper.selectMaps(zidingyi_queryWrapper);
        //由于是List集合，所以我们需要forEach遍历输出
        mapList.forEach(System.out::println);
        return "请回idea控制台查看";
    }
    //注意如果某条数据里有逻辑字段，并且逻辑字段不为空，并且该数据已经被逻辑删除了，那么此时执行这里的查询方法，某数据即使符合条件也不会被查询到

    //-------------------------------组装子查询语句，简单说就是怎么写子查询条件------------------------------

    @GetMapping("/wrapper6") //浏览器访问 http://localhost:8050/wrapper6
    public String wrapper6() {
        //需求: 查询uid小于等于3的用户信息
        //注意: 要用子查询实现
        QueryWrapper<User> zidingyi_queryWrapper = new QueryWrapper<>();
        zidingyi_queryWrapper.inSql("uid","select uid from t_user where uid <= 3");
        //下面那行的右边获取上面那行的条件构造器对象，然后返回值是List集合
        List<User> list = userMapper.selectList(zidingyi_queryWrapper);
        //由于是List集合，所以我们需要forEach遍历输出
        list.forEach(System.out::println);
        return "请回idea控制台查看";
    }
    //注意如果某条数据里有逻辑字段，并且逻辑字段不为空，并且该数据已经被逻辑删除了，那么此时执行这里的查询方法，某数据即使符合条件也不会被查询到

    //------------------------------使用UpdateWrapper类的set方法实现修改功能-----------------------------

    @GetMapping("/wrapper7") //浏览器访问 http://localhost:8050/wrapper7
    public String wrapper7() {
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        //需求: 将用户名中包含小明并且(年龄大于15或邮箱为null)的用户信息修改。注意上面演示过一次，当时用的是QueryWrapper类
        //注意: 需要优先判断括号里的'年龄大于15或邮箱为null'条件
        updateWrapper.like("user_name","小明")
                .and(i->i.gt("age",15).or().isNull("email"));
        updateWrapper.set("user_name","我修改你了").set("email","set@123.com");//用链式编程修改多个字段数据
        userMapper.update(null, updateWrapper);//由于是修改操作，所以第一个参数可以不提供实体类对象。返回值是受影响的行数
        return "修改成功 请到数据库查看";
    }
    //注意如果某条数据里有逻辑字段，并且逻辑字段不为空，并且该数据已经被逻辑删除了，那么此时执行这里的修改方法，该数据即使符合条件也不会被修改到

    //----------------------------------QueryWrapper类的条件删除delete---------------------------------

    @GetMapping("/wrapper8") //浏览器访问 http://localhost:8050/wrapper8
    public String wrapper8() {
        //需求: 删除邮箱地址为null的用户信息
        //由于Mapper类是最顶类，且是抽象类，所以我们需要使用Mapper类的子类，即创建'Mapper类的子类'的对象，因为是删除操作所以创建的是QueryWrapper类的对象
        QueryWrapper<User> zidingyi_queryWrapper = new QueryWrapper<>();
        zidingyi_queryWrapper.isNull("email");//isnNull表示要求哪个字段为空。由于只有一个条件所以不需要使用链式编程
        userMapper.delete(zidingyi_queryWrapper);//返回值是受影响的行数
        return "删除成功 请到数据库查看";
    }
    //注意如果某条数据里有逻辑字段，并且逻辑字段不为空，此时执行这里的删除方法，但是数据并不会真正删除，只是逻辑上的删除
    //虽然我们查询的时候数据是被删除(也就是查询不到)的，但是数据不会被真正删除。当要删除的数据没有逻辑字段时，那么就会被真正删除
}
